﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Transactions;
using System.Web;
using System.Web.Mvc;
using Ninject;
using XHouse.Data.Interfaces;
using XHouse.Model;
using XHouseWeb.Helpers;

namespace XHouseWeb.Controllers
{
    public class AmbientesController : Controller
    {
        private readonly IRepository<Ambiente> _repositorio;
        private readonly ImageProvider _imageProvider;

        [Inject]
        public AmbientesController(IRepository<Ambiente> repository, ImageProvider imageProvider)
        {
            if (repository == null)
                throw new ArgumentNullException("repository");

            if (imageProvider == null)
                throw new ArgumentNullException("imageProvider");

            _imageProvider = imageProvider;
            _repositorio = repository;
        }

        //
        // GET: /Ambientes/
        public ActionResult Index()
        {
            // FIXME: Ese "x => true" es cualquiera. Es un workarround, habría que hacen un GetAll que devuelva un IQueryable
            return View(_repositorio.GetQueryable(x => true).Include(a => a.Aparatos));
        }

        //
        // GET: /Aparatos/Create
        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Aparatos/Create
        [HttpPost]
        public ActionResult Create(Ambiente ambiente)
        {
            // Chequeo si existe otro ambiente con el mismo nombre
            if (!string.IsNullOrEmpty(ambiente.Nombre) && _repositorio.Get(x => x.Nombre.Equals(ambiente.Nombre, StringComparison.OrdinalIgnoreCase)).Any())
                ModelState.AddModelError("AmbienteRepetido", string.Format("Ya existe un ambiente con el nombre <strong>{0}</strong>.", ambiente.Nombre));

            var guardarArchivo = false;
            HttpPostedFileBase file = null;

            // Si hay un archivo, chequeo que sea válido
            if (Request.Files != null && Request.Files.Count > 0)
            {
                file = Request.Files[0];
                if (file != null && file.ContentLength > 0)
                {
                    string[] errorMsg;

                    if (!_imageProvider.ValidateFile(file, out errorMsg))
                    {
                        for (var i = 0; i < errorMsg.Length; i++)
                            ModelState.AddModelError(string.Format("ErrorArchivo-{0}", i), errorMsg[i]);
                    }
                    else
                        guardarArchivo = true;
                }
            }

            // Chequeo si hay errores de validación
            if (!ModelState.IsValid)
                return View(ambiente);

            // Guardo el ambiente
            _repositorio.Add(ambiente);
            _repositorio.Save();

            // Guardo la imagen
            if (guardarArchivo)
                _imageProvider.Save(file, ambiente.Id, ImagenTipoObjeto.Ambiente);

            return RedirectToAction("Index");
        }

        //
        // GET: /Ambientes/Edit/5
        public ActionResult Edit(int id = 0)
        {
            var ambiente = _repositorio.GetQueryable(x => x.Id == id).Include(a => a.Aparatos).First();
            if (ambiente == null)
                return HttpNotFound();

            if (_imageProvider.HaveImage(ImagenTipoObjeto.Ambiente, id))
                ViewBag.SrcImagen = _imageProvider.GetImagePath(ImagenTipoObjeto.Ambiente, id);
            
            return View(ambiente);
        }

        //
        // POST: /Ambientes/Edit/5
        [HttpPost]
        public ActionResult Edit(Ambiente ambiente)
        {
            // Chequeo si existe otro ambiente con el mismo nombre
            if (!string.IsNullOrEmpty(ambiente.Nombre) && _repositorio.Get(x => x.Nombre.Equals(ambiente.Nombre, StringComparison.OrdinalIgnoreCase) && x.Id != ambiente.Id).Any())
                ModelState.AddModelError("AmbienteRepetido", string.Format("Ya existe un ambiente con el nombre <strong>{0}</strong>.", ambiente.Nombre));

            bool borrarImagenAnterior;
            if (!bool.TryParse(Request.Form["hidBorrarImagen"], out borrarImagenAnterior))
                borrarImagenAnterior = false;

            var guardarArchivo = false;
            HttpPostedFileBase file = null;

            if (!_imageProvider.HaveImage(ImagenTipoObjeto.Ambiente, ambiente.Id) || borrarImagenAnterior)
            {
                // Si hay un archivo, chequeo que sea válido
                if (Request.Files != null && Request.Files.Count > 0)
                {
                    file = Request.Files[0];
                    if (file != null && file.ContentLength > 0)
                    {
                        string[] errorMsg;

                        if (!_imageProvider.ValidateFile(file, out errorMsg))
                        {
                            for (var i = 0; i < errorMsg.Length; i++)
                                ModelState.AddModelError(string.Format("ErrorArchivo-{0}", i), errorMsg[i]);
                        }
                        else
                            guardarArchivo = true;
                    }
                }
            }

            // Chequeo si hay errores de validación
            if (!ModelState.IsValid)
                return View(ambiente);

            // Guardo el ambiente
            _repositorio.Update(ambiente);
            _repositorio.Save();

            // Eliminar imagen anterior
            if (borrarImagenAnterior)
                _imageProvider.Remove(ambiente.Id, ImagenTipoObjeto.Ambiente);

            // Guardo la imagen
            if (guardarArchivo)
                _imageProvider.Save(file, ambiente.Id, ImagenTipoObjeto.Ambiente);

            return RedirectToAction("Index");
        }

        //
        // GET: /Ambientes/Delete/5
        public ActionResult Delete(int id)
        {
            Ambiente ambiente = _repositorio.Get(id);
            if (ambiente == null)
                return HttpNotFound();

            using (var tran = new TransactionScope())
            {
                _repositorio.Remove(id);
                _repositorio.Save();

                _imageProvider.Remove(ambiente.Id, ImagenTipoObjeto.Ambiente);

                tran.Complete();
            }
            
            return RedirectToAction("Index");
        }

        //
        // GET: /Escenas/Configure
        public ActionResult Configure(int id)
        {
            var ambiente = _repositorio.Get(id);

            // Imagen de la Ambiente
            ViewBag.PathImagen = Url.Content(_imageProvider.GetImagePath(ImagenTipoObjeto.Ambiente, ambiente.Id));

            // Imagenes de los tipos de aparatos involucrados en la Ambiente
            var pathImgTipoAparatos = new Dictionary<int, string>();

            foreach (var a in ambiente.Aparatos)
            {
                if (pathImgTipoAparatos.ContainsKey(a.TipoAparatoId))
                    continue;

                pathImgTipoAparatos.Add(a.TipoAparatoId,
                                        Url.Content(_imageProvider.GetImagePath(ImagenTipoObjeto.TipoAparato,
                                                                                a.TipoAparatoId)));
            }

            ViewBag.PathImgTipoAparatos = pathImgTipoAparatos;

            return View(ambiente);
        }

        protected override void Dispose(bool disposing)
        {
            _repositorio.Dispose();
            base.Dispose(disposing);
        }
    }
    
}
